package com.beluga.core.util;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * @author iron.guo
 */
public interface IIfUtil {

    IIfUtil build = new IIfUtil() {
    };

    /**
     * 当content满足rule之后将会作为参数执行then并返回执行结果，否则将不会执行then并返回null
     *
     * @param then
     * @param param
     * @param rule
     * @param <P>
     * @param <R>
     * @return
     */
    default <P, R> R thenIf(Function<P, R> then, P param, Predicate<P> rule) {
        return rule.test(param) ? then.apply(param) : null;
    }

    default <P, R> R ifThen(P param, Predicate<P> rule, Function<P, R> then) {
        return rule.test(param) ? then.apply(param) : null;
    }

    default <T, R> R ifOrElseFun(T param, Predicate<T> rule, Function<T, R> then, Function<T, R> orElse) {
        return rule.test(param) ? then.apply(param) : orElse.apply(param);
    }

    default <R> R ifOrElseGet(boolean rule, Supplier<R> then, Supplier<R> orElse) {
        return rule ? then.get() : orElse.get();
    }

    default <T> void ifOrElseVoid(T param, Predicate<T> rule, Consumer<T> then, Consumer<T> orElse) {
        if (rule.test(param)) {
            then.accept(param);
        } else {
            orElse.accept(param);
        }
    }


    default <P> void elseIfVoidByKey(P param, boolean ifRule, Consumer<P> ifThen, boolean elseRule, Consumer<P> elseThen) {
        if (ifRule) {
            ifThen.accept(param);
        } else if (elseRule) {
            elseThen.accept(param);
        }
    }

    default <P> void elseIfVoidByKey(P param, boolean ifRule, Consumer<P> ifThen, boolean elseRule, Consumer<P> elseThen, Consumer<P> defaultThen) {
        if (ifRule) {
            ifThen.accept(param);
        } else if (elseRule) {
            elseThen.accept(param);
        } else {
            defaultThen.accept(param);
        }
    }

    default <P, R> R elseIfFunByKey(P param, boolean ifRule, Function<P, R> ifThen, boolean elseRule, Function<P, R> elseThen) {
        return elseIfFunDefaultValByKey(param, ifRule, ifThen, elseRule, elseThen, null);
    }

    default <P, R> R elseIfFunDefaultValByKey(P param, boolean ifRule, Function<P, R> ifThen, boolean elseRule, Function<P, R> elseThen, R defaultVal) {
        if (ifRule) {
            return ifThen.apply(param);
        } else if (elseRule) {
            return elseThen.apply(param);
        } else {
            return defaultVal;
        }
    }

    default <P, R> R elseIfFunDefaultFunByKey(P param, boolean ifRule, Function<P, R> ifThen, boolean elseRule, Function<P, R> elseThen, Function<P, R> defaultThen) {
        if (ifRule) {
            return ifThen.apply(param);
        } else if (elseRule) {
            return elseThen.apply(param);
        } else {
            return defaultThen.apply(param);
        }
    }

    default <R> R elseIfGetByKey(boolean ifRule, Supplier<R> ifThen, boolean elseRule, Supplier<R> elseThen) {
        return elseIfGetDefaultValByKey(ifRule, ifThen, elseRule, elseThen, null);
    }

    default <R> R elseIfGetDefaultValByKey(boolean ifRule, Supplier<R> ifThen, boolean elseRule, Supplier<R> elseThen, R defaultVal) {
        if (ifRule) {
            return ifThen.get();
        } else if (elseRule) {
            return elseThen.get();
        } else {
            return defaultVal;
        }
    }

    default <R> R elseIfGetDefaultGetByKey(boolean ifRule, Supplier<R> ifThen, boolean elseRule, Supplier<R> elseThen, Supplier<R> defaultGet) {
        if (ifRule) {
            return ifThen.get();
        } else if (elseRule) {
            return elseThen.get();
        } else {
            return defaultGet.get();
        }
    }


    default <P> void elseIfVoidByFields(P param, Predicate<P> ifRule, Consumer<P> ifThen, Predicate<P> elseRule, Consumer<P> elseThen) {
        if (ifRule.test(param)) {
            ifThen.accept(param);
        } else if (elseRule.test(param)) {
            elseThen.accept(param);
        }
    }

    default <P> void elseIfVoidByFields(P param, Predicate<P> ifRule, Consumer<P> ifThen, Predicate<P> elseRule, Consumer<P> elseThen, Consumer<P> defaultThen) {
        if (ifRule.test(param)) {
            ifThen.accept(param);
        } else if (elseRule.test(param)) {
            elseThen.accept(param);
        } else {
            defaultThen.accept(param);
        }
    }

    default <P, R> R elseIfFunByFields(P param, Predicate<P> ifRule, Function<P, R> ifThen, Predicate<P> elseRule, Function<P, R> elseThen) {
        return elseIfFunDefaultValByFields(param, ifRule, ifThen, elseRule, elseThen, null);
    }

    default <P, R> R elseIfFunDefaultValByFields(P param, Predicate<P> ifRule, Function<P, R> ifThen, Predicate<P> elseRule, Function<P, R> elseThen, R defaultVal) {
        if (ifRule.test(param)) {
            return ifThen.apply(param);
        } else if (elseRule.test(param)) {
            return elseThen.apply(param);
        } else {
            return defaultVal;
        }
    }

    default <P, R> R elseIfFunDefaultFunByFields(P param, Predicate<P> ifRule, Function<P, R> ifThen, Predicate<P> elseRule, Function<P, R> elseThen, Function<P, R> defaultThen) {
        if (ifRule.test(param)) {
            return ifThen.apply(param);
        } else if (elseRule.test(param)) {
            return elseThen.apply(param);
        } else {
            return defaultThen.apply(param);
        }
    }

    default <R> R elseIfGetByTest(Supplier<Boolean> ifRule, Supplier<R> ifThen, Supplier<Boolean> elseRule, Supplier<R> elseThen) {
        return elseIfGetDefaultValByTest(ifRule, ifThen, elseRule, elseThen, null);
    }

    default <R> R elseIfGetDefaultValByTest(Supplier<Boolean> ifRule, Supplier<R> ifThen, Supplier<Boolean> elseRule, Supplier<R> elseThen, R defaultVal) {
        if (ifRule.get()) {
            return ifThen.get();
        } else if (elseRule.get()) {
            return elseThen.get();
        } else {
            return defaultVal;
        }
    }

    default <R> R elseIfGetDefaultGetByTest(Supplier<Boolean> ifRule, Supplier<R> ifThen, Supplier<Boolean> elseRule, Supplier<R> elseThen, Supplier<R> defaultGet) {
        if (ifRule.get()) {
            return ifThen.get();
        } else if (elseRule.get()) {
            return elseThen.get();
        } else {
            return defaultGet.get();
        }
    }
}